package controlFlowGraph;

import java.util.ArrayList;
import java.util.List;

import config.GlobalConfig;

import domains.AnalysisDomain;

public class CFGNode {

	/**
	 * 0 -> start
	 * -1 -> end
	 * rest normal
	 */
	private int id;
	
	private List<CFGEdge> inEdges;
	
	private List<CFGEdge> outEdges;
	
	private AnalysisDomain analysisInfo;
	
	public CFGNode(int id) {
		this.id = id;
		this.inEdges = new ArrayList<CFGEdge>();
		this.outEdges = new ArrayList<CFGEdge>();
	}
	
	public void addInEdge(CFGEdge e) {
		this.inEdges.add(e);
	}
	
	public void addOutEdge(CFGEdge e) {
		this.outEdges.add(e);
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof CFGNode) {
			CFGNode n = (CFGNode) obj;
			return n.getId() == this.getId();
		}
		return false;
	}

	@Override
	public int hashCode() {
		return id;
	}

	@Override
	public String toString() {
		return "Node" + id;
	}

	public int getId() {
		return id;
	}
	
	public AnalysisDomain getAnalysisInfo() {
		return this.analysisInfo;
	}
	
	public void setAnalysisInfo(AnalysisDomain res) {
		this.analysisInfo = res;
	}

	public List<CFGEdge> getInEdges() {
		return this.inEdges;
	}
	
	public List<CFGEdge> getOutEdges() {
		return this.outEdges;
	}

	public void clearOutEdges() {
		this.outEdges = new ArrayList<CFGEdge>();
	}
	
	public String toGraphVisualization() {
		if (CFG.alreadyLabeled.contains(this)) {
			return "";
		}
		String result = "";
		CFG.alreadyLabeled.add(this);
		for (CFGEdge edge : this.getOutEdges()) {
			String id1 = (this.getId() < 0) ? "new"+(this.getId()*(-1)) : ""+this.getId();
			String id2 = (edge.getToNode().getId() <0) ?
					"new" + (edge.getToNode().getId()*(-1)) : ""+edge.getToNode().getId();
			result += "label" + id1 + " -> " + "label"	+ id2 + " [label=\"" 
						+ edge.getLabel() + "\"];\n";
			result += edge.getToNode().toGraphVisualization();
		}
		return result;
	}

	public String asOutput() {
		if (CFG.alreadyLabeled.contains(this)) {
			return "";
		}
		String result = "";
		CFG.alreadyLabeled.add(this);
		for (CFGEdge edge : this.getOutEdges()) {
			String id1 = (this.getId() < -1) ? "N"+(this.getId()*(-1)) : "P"+this.getId();
			id1 = (id1.equals("P0")) ? "START" : id1;
			String id2 = (edge.getToNode().getId() < -1) ?
					"N" + (edge.getToNode().getId()*(-1)) : "P"+edge.getToNode().getId();
			id2 = (id2.equals("P0")) ? "START" : id2;
			id2 = (id2.equals("P-1")) ? "END" : id2;
			String spaces1 = "";
			for(int i = GlobalConfig.firstColumnWidth-id1.length(); i >= 0; i--) {
				spaces1 += " ";
			}
			String spaces2 = "";
			for(int i = GlobalConfig.secondColumnWidth-edge.getLabel().toString().length(); i >= 0; i--) {
				spaces2 += " ";
			}
			result += "   " + id1 + spaces1 + edge.getLabel() + spaces2 + id2 + "\n";
			result += edge.getToNode().asOutput();
		}
		return result;
	}
}
